#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include "../include/queries.h"
#include "../databaseADT/databaseADT.h"
#include "../../common/include/common.h"
#include "../../common/include/general.h"
#include "../../common/include/split.h"
#include "../../common/include/filesystem.h"
#include "../../common/include/menu.h"
#include "../include/server.h"

#include "../include/pipeserver.h"
#include "../../common/include/commonPI.h"

#include "../include/MQserver.h"
#include "../../common/include/commonMQ.h"

#include "../include/shm_server.h"
#include "../../common/include/commonSHM.h"

#include "../include/TCPserver.h"
#include "../../common/include/commonTCP.h"


/*Variables para split */
char splitVal;
splitNode splits[MAX_SPLITS];

/* Flag para el ciclo de escucha del cliente */
int doLC = 1;

int
main (int argc, char ** argv)
{
    appInit params;

    /*TODO: DEBUG */
    rm("./database.db");

    getParameters(argc, argv, &params);

    if (!validateParameters(&params))
    {
        usage(argv[0]);
        return 0;
    }

    if (deleteOnline() != DB_SUCCESS)
    {
        fatal ("DB failure\n");
        return 0;
    }

    /* Lógica de inicialización del programa con params */
    splitVal = params.split;
    initSplits(splits);

    switch(params.ipc)
    {
        case 'p':
            mainPI();
            break;

        case 'q':
              mainMQ();
            break;

        case 'm':
            mainSM();
            break;

        case 's':
              mainTCP();
            break;

        default:
            printf("IPC selected doesn't exist\n");
            break;
    }

    freedatabase();
    freeParameters(&params);

    return 0;
}

void
initSplits(splitNode *splits)
{
    int i;

    if (splits == NULL)
        return;

    for (i=0 ; i < MAX_SPLITS; i++)
        insertOnline(i, NULL, 0);

    return;
}

void usuarios(char * param)
{
    queueADT usrs;
    int cant;
    char * name;


    usrs = listUsr();
    cant = queueLength(usrs);

    printf ("Users list:\n");


    while (cant--)
    {
        name = (char *)dequeue ( usrs );

        printf("<- %s ->\n", name);
    }


    freeQueue( usrs );
    return;
}

void registrar(char * param)
{
    char dir[MAX_DIR_LEN + 1] = {0};
    char path[MAX_DIR_LEN*2] = {0};

    fprintf (stdout, "Insert dir: ");
    getLine (dir, MAX_DIR_LEN, stdin);

    sprintf(path, "%s/%s", ".", dir);

    if (isDir(path) == 1)
    {
        if ( (addDir(dir)) != DB_SUCCESS)
            printf("Couldn't add %s\n", dir);
        else
            printf("%s Added successfully\n", dir);
    }
    else
        printf("%s is not a directory\n", dir);

    return;
}

void
dir(char * param)
{
    queueADT dirs;
    int cant, i;
    char *str = NULL;

    char usr[MAX_USER_LEN + 1] = {0};
    fprintf (stdout, "Insert user: ");
    getLine (usr, MAX_USER_LEN, stdin);

    dirs = listDirPerUser(usr);
    cant = queueLength(dirs);

    printf ("%s has synched %d dirs.\n\n", usr, cant);

    for ( i = 0 ; i < cant ; i++ )
    {
        str = (char *)dequeue ( dirs );
        printf("%2d %s.\n", i+1, str);
        free(str);
    }

    freeQueue( dirs );
    return;
}

void
last10(char * param)
{
    queueADT q = NULL;
    char *str = NULL;
    q = qLast10(NULL);
    int i = 1;

    printf("\nLast 10 actions\n\n");
    while( (str = dequeue(q)) != NULL)
    {
        printf("%2d %s.\n", i++, str);
        free(str);
    }

    freeQueue(q);
    return;
}
void ulast10(char * param)
{
    queueADT q = NULL;
    char *str = NULL;
    int i = 1;

    char usr[MAX_USER_LEN + 1] = {0};
    fprintf (stdout, "Insert user: ");
    getLine (usr, MAX_USER_LEN, stdin);

    if ( (userID(usr)) == -1)
    {
        printf("User %s doesn't exists\n", usr);
        return;
    }

    q = qLast10(usr);

    printf("\nLast 10 actions from %s\n\n", usr);
    while( (str = dequeue(q)) != NULL)
    {
        printf("%2d %s.\n", i++, str);
        free(str);
    }

    freeQueue(q);
    return;
}

int getDir (char * dir, char * path)
{
    int i = 0;
    char * inicio;
    char * fin;

    if (path == NULL || dir == NULL)
        return -1;

    inicio = strchr(path, '/');
    inicio += 1;
    fin = strchr(inicio, '/');



    if (inicio == NULL || fin == NULL)
        return -1;

    while (inicio != fin)
    {
        dir[i] = *inicio;
        inicio++;
        i++;
    }

    dir[i] = 0;

    return i - 1;

}

void newDir (char * param)
{
    char dir[MAX_DIR_LEN + 1] = {0};
    fprintf (stdout, "Insert dir: ");
    getLine (dir, MAX_DIR_LEN, stdin);

    if ( (addDir(dir)) != DB_SUCCESS)
        printf("Couldn't add %s\n", dir);
    else
        printf("%s Added successfully\n", dir);

    return;
}

void getDirType(char * params, char * dir, int * type)
{
    char c;
    int i = 0;

    do{
        c = params[i];
        dir[i++] = c;
    }while(c != ',');

    dir[i-1] = 0;
    sscanf(params + i, "%d", type);

    return;
}
